/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.fullhappy.dao;

import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;
import javax.persistence.RollbackException;
import org.eclipse.persistence.exceptions.DatabaseException;

/**
 *
 * @author hiep
 */
public  class AbstractFacade<T> {

    private Class<T> entityClass;

    public AbstractFacade(Class<T> entityClass) {
        this.entityClass = entityClass;
    }
    private EntityManager em = EMF.get().createEntityManager();//Persistence.createEntityManagerFactory("fhpPU").createEntityManager();

    protected EntityManager getEntityManager() {
        if (!em.isOpen()) {
            em = EMF.get().createEntityManager();//Persistence.createEntityManagerFactory("fhpPU").createEntityManager();
        }
        return em;
    }

//    public void create(T entity) {
//        getEntityManager().persist(entity);
//    }
//
//    public void edit(T entity) {
//        getEntityManager().merge(entity);
//    }

    public void remove(T entity) throws Exception {
        EntityTransaction txn = getEntityManager().getTransaction();
        txn.begin();
        try {
            getEntityManager().remove(getEntityManager().merge(entity));
            txn.commit();
        } catch (RollbackException e) {
            Throwable t = e.getCause();
            if (t != null && t instanceof DatabaseException) {
                throw (DatabaseException) t;
            }
            throw e;
        } catch (Exception e) {
            throw e;
        } finally {
            if (txn.isActive()) {
                txn.rollback();
            }
            //getEntityManager().close();
        }
        
    }

    public T create(T entity) throws Exception {
        EntityTransaction txn = getEntityManager().getTransaction();
        txn.begin();
        try {
            getEntityManager().persist(entity);
            txn.commit();
            return entity;
        } catch (RollbackException e) {
            Throwable t = e.getCause();
            if (t != null && t instanceof DatabaseException) {
                throw (DatabaseException) t;
            }
            throw e;
        } catch (Exception e) {
            throw e;
        } finally {
            if (txn.isActive()) {
                txn.rollback();
            }
            //getEntityManager().close();
        }
    }

    public void edit(T entity) throws Exception {
        EntityTransaction txn = getEntityManager().getTransaction();
        txn.begin();
        try {
            getEntityManager().merge(entity);
            //getEntityManager().flush();
            txn.commit();
        } catch (Exception e) {
            throw e;
        } finally {
            if (txn.isActive()) {
                txn.rollback();
            }
            //getEntityManager().close();
        }
    }

    public T find(Object id) {
        return getEntityManager().find(entityClass, id);
    }

    public List<T> findAll() {
        javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
        cq.select(cq.from(entityClass));
        return getEntityManager().createQuery(cq).getResultList();
    }

    public List<T> findRange(int[] range) {
        javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
        cq.select(cq.from(entityClass));
        javax.persistence.Query q = getEntityManager().createQuery(cq);
        q.setMaxResults(range[1] - range[0]);
        q.setFirstResult(range[0]);
        return q.getResultList();
    }

    public int count() {
        javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
        javax.persistence.criteria.Root<T> rt = cq.from(entityClass);
        cq.select(getEntityManager().getCriteriaBuilder().count(rt));
        javax.persistence.Query q = getEntityManager().createQuery(cq);
        return ((Long) q.getSingleResult()).intValue();
    }
}
